﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Media;
using System.Windows.Forms;
using CloudShot.Properties;
using CloudShot.States;
using CloudShot.Utils;

namespace CloudShot
{
	public partial class ShotForm : Form
	{
		private readonly IShotState _state;
		public Image Image { get; private set; }

		public ShotForm()
		{
			InitializeComponent();

			//this code must be here, you must set beckground before form takes focus
			ScreenCapture sc = new ScreenCapture();
			this.BackgroundImageLayout = ImageLayout.None;
			this.BackgroundImage = sc.CaptureRectangle(GetScreenSize());
			this.Icon = Resources.applicationIcon;

			//SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			//SetStyle(ControlStyles.UserPaint, true);
			//SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

			//_state = new GeneralState( this );
            _state = new ShotState(this);
		}

		private void ShotForm_Load(object sender, EventArgs e)
		{
			Rectangle rect = GetScreenSize();

			Location = rect.Location;
			Size = rect.Size;

#if DEBUG
			this.TopMost = false;
#endif
		}

		private static Rectangle GetScreenSize()
		{
			int left = 0;
			int top = 0;
			int right = 0;
			int bottom = 0;

			//при фотографировании окон надо учитывать что координаты на primary screen могут быть отрицательными (Y = -124)
			//http://dl.dropbox.com/u/145751/%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE%20%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D1%8F%D1%8E%D1%82%D1%81%D1%8F%20%D0%BA%D0%BE%D0%BE%D1%80%D0%B4%D0%B8%D0%BD%D0%B0%D1%82%D1%8B%20%D0%BE%D0%BA%D0%BD%D0%B0%20%D0%BF%D1%80%D0%B8%20%D1%82%D0%B0%D0%BA%D0%BE%D0%BC%20%D1%81%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B8.png

			foreach (Screen screen in Screen.AllScreens)
			{
				left = Math.Min(left, screen.Bounds.Left);
				top = Math.Min(top, screen.Bounds.Top);
				right = Math.Max(right, screen.Bounds.Right);
				bottom = Math.Max(bottom, screen.Bounds.Bottom);
			}

			Rectangle rect = new Rectangle(left, top, right - left, bottom - top);

			return rect;
		}

		private void ShotForm_MouseDown(object sender, MouseEventArgs e)
		{
			if (e.Button != MouseButtons.Left)
			{
				_state.End();
				DialogResult = DialogResult.Cancel;
				Close();
				return;
			}
			_state.Start(e.Location);
		}

		private void ShotForm_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button != MouseButtons.Left)
			{
				Close();
				return;
			}

			_state.End();
			Image = _state.Shot();

			if (Image == null)
				DialogResult = DialogResult.Cancel;

			DialogResult = DialogResult.OK;
			Close();
		}

		private Point _lastLocation;

		protected override void OnMouseMove(MouseEventArgs e)
		{
			//base.OnMouseMove(e);
			if (_lastLocation == e.Location)
				return;

			_lastLocation = e.Location;
			_state.Update(e.Location);
			Invalidate();
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			//base.OnPaint(e);
			//Stopwatch myStopwatch = new Stopwatch();

			//myStopwatch.Start();
			e.Graphics.CompositingQuality = CompositingQuality.HighSpeed;
			e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
			e.Graphics.InterpolationMode = InterpolationMode.Low;
			e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
			e.Graphics.CompositingMode = CompositingMode.SourceOver;

			_state.Paint(e.Graphics);
			//myStopwatch.Stop();

			// Get the elapsed time as a TimeSpan value.
			//TimeSpan ts = myStopwatch.Elapsed;

			// Format and display the TimeSpan value.
			//string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
			//Trace.WriteLine(elapsedTime, "RunTime");
		}

		private void ShotForm_Deactivate(object sender, EventArgs e)
		{
			Close();
		}

		private void ShotForm_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Escape)
			{
				_state.End();
				DialogResult = DialogResult.Cancel;
				Close();
			}
			else if (e.KeyCode == Keys.V && e.Modifiers == Keys.Control)
			{
				string text = Clipboard.GetText();
				if (!string.IsNullOrEmpty(text))
				{
					_typedText += text;
					_state.Type(_typedText);
				}
			}

		}

		private string _typedText = string.Empty;

		private void ShotForm_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\b')//backspace
			{
				if (!string.IsNullOrEmpty(_typedText))
				{
					_typedText = _typedText.Remove(_typedText.Length - 1);
					_state.Type(_typedText);
				}

			}
			else if (char.IsLetterOrDigit(e.KeyChar) || char.IsPunctuation(e.KeyChar) || char.IsWhiteSpace(e.KeyChar))
			{
				_typedText += e.KeyChar;
				_state.Type(_typedText);
			}

		}
	}
}
